package home.contaduria.service.impl;

import home.contaduria.dao.ClientDao;
import home.contaduria.dao.IncomeDao;
import home.contaduria.dao.IncomeTypeDao;
import home.contaduria.domain.Client;
import home.contaduria.domain.Income;
import home.contaduria.domain.IncomeType;
import home.contaduria.service.IncomeService;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("incomeService")
public class IncomeServiceImpl implements IncomeService {
    private static final Logger logger = LoggerFactory.getLogger(IncomeServiceImpl.class);

    private IncomeDao incomeDao;
    private IncomeTypeDao incomeTypeDao;
    private ClientDao clientDao;

    @Autowired
    public IncomeServiceImpl(IncomeDao incomeDao, IncomeTypeDao incomeTypeDao, ClientDao clientDao) {
        this.incomeDao = incomeDao;
        this.incomeTypeDao = incomeTypeDao;
        this.clientDao = clientDao;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createIncome(Income income) {
        updateIncomeType(income);

        Client persistentClient = clientDao.read(income.getClient().getId());
        income.setClient(persistentClient);

        logger.info("Creating income {}", income);

        incomeDao.create(income);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Income readIncome(Long id) {
        return incomeDao.read(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateIncome(Income income) {
        updateIncomeType(income);
        incomeDao.update(income);
        logger.info("Updating income {}", income);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteIncome(Long id) {
        Income income = incomeDao.read(id);
        incomeDao.delete(income);
        logger.info("Removing income {}", income);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<Income> listIncomes(Client client) {
        return incomeDao.findIncomes(client);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<Income> listIncomes(Client client, int firstResult, int maxResults) {
        return incomeDao.findIncomes(client, firstResult, maxResults);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long countIncomesNumber(Client client) {
        return incomeDao.countIncomesNumber(client);
    }

    private void updateIncomeType(Income income) {
        IncomeType incomeType = income.getType();
        IncomeType existingIncomeType = incomeTypeDao.findIncomeType(incomeType.getName(), income.getClient());
        if (existingIncomeType != null) {
            logger.debug("Use existing incomeType {} in income", existingIncomeType);
            incomeType = existingIncomeType;
        } else {
            logger.debug("Create a new income type {} for client {}", incomeType.getName(), income.getClient());
            incomeType.setClient(income.getClient());
            incomeTypeDao.create(incomeType);
        }
        income.setType(incomeType);
    }

}
